/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package net.ubinow.mflex.widgets;


import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;

import net.ubinow.mflex.baseui.IWidget;
import net.ubinow.mflex.baseui.WFont;
import net.ubinow.mflex.baseui.WidgetContainer;
import net.ubinow.mflex.events.Event;
import net.ubinow.mflex.events.IEventSubscriber;
import net.ubinow.mflex.util.Constants;
import net.ubinow.mflex.util.KeyConstants;
import net.ubinow.mflex.util.MiscUtil;

/**
 *
 * @author Josh
 */
public class DialogView extends AbsView{

    public static final String DEFAULT_LEFT_CMD_TEXT    = "Cancel";
    public static final String DEFAULT_RIGHT_CMD_TEXT   = "Ok";
    
    public static final int STATE_HIDDEN                = 0;
    public static final int STATE_OPENING               = 1;
    public static final int STATE_OPENED                = 2;
    public static final int STATE_CLOSING               = 3;    
    
    private int _state = STATE_HIDDEN;
    
    // dialog image details
    private Image _dialogImage;
    private int _diHeaderHeight = 0;
    private int _diFooterHeight = 0;
    private int _diTileWidth = 0;
    private int _diTileHeight = 0;
    
    // title stuff
    private Image _titleImage;
    private String _titleText;
    private int _titlePaddingX = 0;
    private int _titlePaddingY = 0;
    private int _titleAlignmentX = Constants.ALIGN_CENTRE_H;
    private int _titleAlignmentY = Constants.ALIGN_CENTRE_V;
    private int _titleX = 0;
    private int _titleY = 0;
    
    private String _leftCmdText = DEFAULT_LEFT_CMD_TEXT;
    private String _rightCmdText = DEFAULT_RIGHT_CMD_TEXT; 
    private int _cmdPaddingX = 5; // padding from the side of the dialog 
    private int _cmdPaddingY = 5; // padding from the bottom of the dialog 
    
    IEventSubscriber _subscriber;
    private int _curWidth = 0;
    private int _curHeight = 0;
    
    // widget stuff
    private WidgetContainer _wContainer;
    private int _containerPaddingX = 5;
    private int _containerPaddingY = 3; 
    
    private boolean _submittedPressed = false; 
    
    public DialogView( int x, int y, int width, int height, WFont defaultFont, IEventSubscriber subscriber ){
        super( x, y, width, height, defaultFont );
        
        _subscriber = subscriber;
        
        addEventSubscriber( Event.EVT_VIEW_SHOWING, subscriber );
        addEventSubscriber( Event.EVT_VIEW_HIDING, subscriber );
                
    }        
    
    private void initWidgetContainer(){
        _viewableHeight = _height - _diHeaderHeight - _diFooterHeight - _containerPaddingX;
        _viewableWidth = _width - _containerPaddingY; 
        
        _wContainer = new WidgetContainer( _x+_containerPaddingX, _y+_diHeaderHeight+_containerPaddingY, 
                _viewableWidth, _viewableHeight );
        
        _wContainer.setPaddingH( 0 );
        _wContainer.setPaddingW( 0 );
        _wContainer.addEventSubscriber( Event.EVT_ANY, this );
        _wContainer.setFont( _bodyFont );
    }
    
    //<editor-fold defaultstate="collapsed" desc="overrides">
    
    public boolean isVisible() {
        return _state == STATE_OPENED || _state == STATE_CLOSING || _state == STATE_OPENING;
    }
    
    public void setFont( WFont font ){
        super.setFont( font );
        if( _wContainer != null )
            _wContainer.setFont( font );
    }
    
    public void setCommandFont( WFont font ){
        super.setCommandFont( font ); 
        resetTitleAlignment();
    }
    
    //</editor-fold>
    
    //<editor-fold defaultstate="collapsed" desc="getters/setters">
    
    public void show(){
        if( _state != STATE_OPENED && _state != STATE_OPENING ){
            _state = STATE_OPENING;
            _curWidth = 10;
            _curHeight = 10;
            _submittedPressed = false; 
        }
    }
    
    public void hide(){
        if( _state == STATE_OPENING || _state == STATE_OPENED )
            _state = STATE_CLOSING;
    }
    
    /** 
     * 
     * @return true if the user clicked on the submit button otherwise flase to indicate the user canceled the dialog
     */
    public boolean userSubmittedForm(){
        return _submittedPressed;
    }
    
    public int getState(){
        return _state;
    }
    
    public void setContainerPadding( int paddingX, int paddingY ){
        _containerPaddingX = paddingX;
        _containerPaddingY = paddingY;
    }
    
    public void setTitle( String title, int alignmentX, int alignmentY, int paddingX, int paddingY ){
        _titleImage = null;
        _titleText = title; 
        _titleAlignmentX = alignmentX;
        _titleAlignmentY = alignmentY;
        _titlePaddingX = paddingX;
        _titlePaddingY = paddingY;
        
        resetTitleAlignment();
    }
    
    public void setTitle( Image title, int alignmentX, int alignmentY, int paddingX, int paddingY ){
        _titleImage = title;
        _titleText = null; 
        _titleAlignmentX = alignmentX;
        _titleAlignmentY = alignmentY;
        _titlePaddingX = paddingX;
        _titlePaddingY = paddingY;
        
        resetTitleAlignment();
    }
    
    public void setDialogImage( Image img, int dialogHeaderHeight, int dialogFooterHeight, int dialogTileWidth, int dialogTileHeight ){
        _dialogImage = img;
        _diHeaderHeight = dialogHeaderHeight;
        _diFooterHeight = dialogFooterHeight;
        _diTileWidth = dialogTileWidth;
        _diTileHeight = dialogTileHeight;
    }
    
    public void setCommandText( String lCmd, String rCmd ){
        _leftCmdText = lCmd;
        _rightCmdText = rCmd;
    } 
    
    /**
     * 
     * @param paddingX: padding from the edge of the dialog 
     * @param paddingY: padding from the bottom of the dialog 
     */
    public void setCommandTextPadding( int paddingX, int paddingY ){
        _cmdPaddingX = paddingX;
        _cmdPaddingY = paddingY;
    }   
    
    //</editor-fold>
    
    //<editor-fold defaultstate="collapsed" desc="widget handling methods">
    
    private boolean _hasSelectedWidget = false; 
    
    public void addWidget( IWidget widget ){
        if( _wContainer == null )
            initWidgetContainer();
        
        _wContainer.addWidget( widget, false );
        
        // if the first widget then set to selected
        if( !_hasSelectedWidget && widget.isSelectable() ){
            _wContainer.setFocus( widget );
            _hasSelectedWidget = true; 
        }     
    }        
    
    public IWidget getWidget( String id ){
        return _wContainer.getWidget( id );
    }
    
    //</editor-fold>
    
    //<editor-fold defaultstate="collapsed" desc="AbsView abstract method implementations">
    
    public void cycle() {
        // animate either growing or shrinking dialog 
        if( _state == STATE_OPENING ){
            if( _curHeight < _height)
                _curHeight += MiscUtil.getInstance().calcHalfDistance( _height, _curHeight );
            
            if( _curWidth < _width )
                _curWidth += MiscUtil.getInstance().calcHalfDistance( _width, _curWidth );
            
            if( _curHeight >= _height )
                _curHeight = _height;
            
            if( _curWidth >= _width )
                _curWidth = _width;
            
            if( _curHeight == _height && _curWidth == _width ){
                _state = STATE_OPENED;
                
                notifySubscribers( getEvet( Event.EVT_VIEW_SHOWING ) );
            }
        }
        else if( _state == STATE_CLOSING ){
            if( _curHeight > 10 )
                _curHeight += MiscUtil.getInstance().calcHalfDistance( 10, _curHeight );
            if( _curWidth > 10 )
                _curWidth += MiscUtil.getInstance().calcHalfDistance( 10, _curWidth );
            
            if( _curHeight <= 10 )
                _curHeight = 10;
            
            if( _curWidth <= 10 )
                _curWidth = 10;
            
            if( _curHeight == 10 && _curWidth == 10 ){
                _state = STATE_HIDDEN;
                
                notifySubscribers( getEvet( Event.EVT_VIEW_HIDING ) );            
            }
        }
    }

    protected int prevX = 0;
    protected int prevY = 0;
    protected int prevWidth = 0;
    protected int prevHeight = 0;
    
    public void paint(Graphics g, int offsetX, int offsetY, int layer) {
        
        boolean clipped = false; 
        
        if( _state == STATE_OPENING || _state == STATE_CLOSING ){
            clipped = true;
            prevX = g.getClipX();
            prevY = g.getClipY();
            prevWidth = g.getClipWidth();
            prevHeight = g.getClipHeight();
            g.setClip( offsetX + _x + ((_width-_curWidth)>>1), 
                    offsetY + _y+ ((_height-_curHeight)>>1), _curWidth, _curHeight );
        }
        
        if( _state == STATE_OPENING || _state == STATE_OPENED || _state == STATE_CLOSING ){
            if( _width == _dialogImage.getWidth() && _height == _dialogImage.getHeight() ){
                g.drawImage( _dialogImage, _x + offsetX, _y + offsetY, Constants.GFX_ALIGN_TOP_LEFT );
            }
            else{
                // TODO: implement drawing a dynamically sized image for the dialog
            }
            
            if( _state == STATE_OPENED ){
                // title
                if( _titleImage != null ){
                    g.drawImage(_titleImage, _x+offsetX+_titleX, _y+offsetY+_titleY, Constants.GFX_ALIGN_TOP_LEFT );
                }
                else if( _titleText != null ){
                    _headerFont.drawString( g, _titleText, _x+offsetX+_titleX, _y+offsetY+_titleY );
                }
                
                // widget container 
                _wContainer.paint( g, offsetX, offsetY, 1, clipped );
                
                // command buttons 
                _commandFont.drawString( g, _leftCmdText, _x+offsetX+_cmdPaddingX, _y+_height-_cmdPaddingY-_commandFont.getHeight() );
                _commandFont.drawString( g, _rightCmdText, 
                        _x+offsetX+_width+_cmdPaddingX-_diTileWidth, _y+_height-_cmdPaddingY-_commandFont.getHeight() );                
                
            }
        }
        
        if( _state == STATE_OPENING || _state == STATE_CLOSING ){
            // un clip
            g.setClip( prevX, prevY, prevWidth, prevHeight );
        }
    }

    public boolean handleKeyPressed(int action, int keyCode) {
        if( _state != STATE_OPENED )
            return false;
        
        if( keyCode == KeyConstants.LEFT_SOFT_BUTTON ){
            _state = STATE_CLOSING;
            _submittedPressed = false; 
            return true; 
        }
        else if( keyCode == KeyConstants.RIGHT_SOFT_BUTTON ){
            _state = STATE_CLOSING;
            _submittedPressed = true; 
            return true; 
        } 
        else{
            return _wContainer.handleKeyPressed( action, keyCode );
        }
    }

    public boolean handleKeyReleased(int action, int keyCode) {
        return _wContainer.handleKeyReleased( action, keyCode );
    }
    
    //</editor-fold>
    
    //<editor-fold defaultstate="collapsed" desc="private helper methods">
    
    private void resetTitleAlignment(){
        int w = 0;
        int h = 0;
        if( _titleImage != null ){
            w = _titleImage.getWidth();
            h = _titleImage.getHeight();
        }
        else if( _titleText != null ){
            w = _commandFont.stringWidth( _titleText );
            h = _commandFont.getHeight();
        }
        else{
            return; 
        }
        
        // x position 
        _titleX = _titlePaddingX; // default left
        if( _titleAlignmentX == Constants.ALIGN_CENTRE ){
            _titleX = ((_width-w-_titlePaddingX)>>1);
        }
        else if( _titleAlignmentX == Constants.ALIGN_RIGHT ){
            _titleX = _width-w-_titlePaddingX;
        }
        
        // y position 
        _titleY = ((_diHeaderHeight-h-_titlePaddingY)>>1);
        if( _titleAlignmentY == Constants.ALIGN_TOP ){
            _titleY = _titlePaddingY;
        }
        else if( _titleAlignmentY == Constants.ALIGN_BOTTOM ){
            _titleY = _diHeaderHeight-_titlePaddingY-h;
        }
        
    }
    
    //</editor-fold>

}
